package com.github.dengmin.mysql.shiro.service;

import com.github.dengmin.mysql.shiro.cache.LoginRedisService;
import com.github.dengmin.mysql.shiro.jwt.JwtProperties;
import com.github.dengmin.mysql.shiro.jwt.JwtToken;
import com.github.dengmin.mysql.shiro.jwt.JwtUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Date;

/**
 * @Author dengmin
 * @Created 2020/8/17 上午10:04
 */
@Service
public class ShiroLoginServiceImpl implements ShiroLoginService{
    private static final long serialVersionUID = 1L;

    @Lazy
    @Autowired
    private JwtProperties jwtProperties;

    @Lazy
    @Autowired
    private LoginRedisService loginRedisService;

    @Override
    public void refreshToken(JwtToken jwtToken, HttpServletResponse httpServletResponse) throws Exception{
        if(null == jwtToken) return;
        String token = jwtToken.getToken();
        if(StringUtils.isBlank(token)) return;
        boolean isRefreshToken = jwtProperties.isRefreshToken();
        if(!isRefreshToken) return;

        Date expireDate = JwtUtil.getExpireDate(token);
        Integer countdown = jwtProperties.getRefreshTokenCountdown();
        boolean refresh = DateUtils.addSeconds(new Date(), countdown).after(expireDate);
        if(!refresh) return;

        boolean exists = loginRedisService.exists(token);
        if(!exists){
            httpServletResponse.setStatus(461);
            throw new AuthenticationException("Token已失效, 请重新授权");
        }
        String username = jwtToken.getUsername();
        String salt = jwtToken.getSalt();
        Long expireSecond = jwtProperties.getExpireSecond();

        String newToken = JwtUtil.generateToken(username, salt, Duration.ofSeconds(expireSecond));
        JwtToken newJwtToken = JwtToken.build(newToken, username, salt, expireSecond);
        loginRedisService.refreshLoginInfo(token, username, newJwtToken);

        httpServletResponse.setHeader("token", newToken);

    }
}
